package com.example.sunrisesunsetview

import android.content.Context
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Rect
import android.util.AttributeSet
import android.view.View
import androidx.annotation.FloatRange
import kotlin.math.asin
import kotlin.math.cos
import kotlin.math.pow
import kotlin.math.sin
import kotlin.math.sqrt

class SunView(context: Context, attributeSet: AttributeSet) : View(context, attributeSet) {

    private val icon by lazy {
        BitmapFactory.decodeResource(resources, R.drawable.icon_sun)
    }

    private val bg by lazy {
        BitmapFactory.decodeResource(resources, R.drawable.sunrise_bg)
    }

    private var progress: Float = 0.0f

    init {
        val typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.SunView)
        progress = typedArray.getFloat(R.styleable.SunView_progress, 0f)
        typedArray.recycle()
        setProgress(progress.toDouble())
    }



    val paint = Paint().apply {
        isAntiAlias = true
        isFilterBitmap = true
    }

    val paint1 = Paint().apply {
        color = Color.BLACK
        style = Paint.Style.STROKE
        strokeWidth = 2f
    }

    val paint2 = Paint().apply {
        color = Color.YELLOW
        style = Paint.Style.STROKE
        strokeWidth = 2f
    }

    val paint3 = Paint().apply {
        color = Color.RED
        style = Paint.Style.STROKE
        strokeWidth = 6f
    }


    private var progressDegrees: Double = 0.0
    private var angleInDegrees: Double = 0.0
    private var radius: Double = 0.0
    private lateinit var srcRect: Rect
    private lateinit var dstRect: Rect
    private var startAngle: Float = 0f
    private var xCenter: Float = 0f
    private var yCenter: Float = 0f
    private lateinit var archRect: Rect

    private lateinit var point0: Point
    private lateinit var point1: Point
    private lateinit var point2: Point

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        val topPoint = icon.height / 2
        val leftPoint = icon.width / 2
        val rightPoint = w - icon.width / 2
        val bottomPoint = h - icon.height / 2

        point0 = Point(leftPoint.toDouble(), bottomPoint.toDouble())
        point1 = Point(rightPoint.toDouble(), bottomPoint.toDouble())
        point2 = Point((leftPoint + rightPoint) / 2.0, topPoint.toDouble())
        val chord = distance(point0, point1)

        radius = circleRadius(point0, point2, point1)
        angleInDegrees = circleArc(radius,chord)
        srcRect = Rect(0, 0, bg.width, bg.height)
        dstRect = Rect(leftPoint, topPoint, rightPoint, bottomPoint)
        startAngle = (3 * 90 - angleInDegrees / 2).toFloat()

        val left = -(radius - (rightPoint + leftPoint) / 2).toFloat()
        val right = (left + 2 * radius).toFloat()
        val bottom = topPoint + 2 * radius.toFloat()
        archRect = Rect(left.toInt(), topPoint, right.toInt(), bottom.toInt())
        xCenter = (left + right) / 2
        yCenter = (topPoint + bottom) / 2
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        drawTrack(canvas)
        drawSun(canvas)
    }

    private fun drawTrack(canvas: Canvas) {
        canvas.drawBitmap(bg, srcRect, dstRect, paint)
    }

    private fun drawSun(canvas: Canvas) {

        val (x, y) = getXY(
            xCenter, yCenter, radius, startAngle + progressDegrees * angleInDegrees
        )

        if(x >= point0.x && x <= point1.x){
            canvas.drawBitmap(icon, x - icon.width / 2, y - icon.height / 2, paint)
        }
    }

    fun setProgress(@FloatRange(from = 0.0, to = 1.0) progress: Double) {
        progressDegrees = progress
        invalidate()
    }

    private fun getXY(
        xCenter: Float, yCenter: Float, radius: Double, angleInDegrees: Double
    ): Pair<Float, Float> {
        val angleInRadians = Math.toRadians(angleInDegrees)
        val x = xCenter + radius * cos(angleInRadians)
        val y = yCenter + radius * sin(angleInRadians)
        return Pair(x.toFloat(), y.toFloat())
    }

    private fun circleArc(radius: Double, chord: Double): Double {
        val radian = 2 * asin(chord / (2 * radius))
        return radian * 180.0 / Math.PI
    }

    data class Point(val x: Double, val y: Double)

    private fun distance(p1: Point, p2: Point): Double {
        return sqrt((p1.x - p2.x).pow(2) + (p1.y - p2.y).pow(2))
    }

    private fun circleRadius(p1: Point, p2: Point, p3: Point): Double {
        val a = distance(p1, p2)
        val b = distance(p2, p3)
        val c = distance(p3, p1)
        val s = (a + b + c) / 2
        val area = sqrt(s * (s - a) * (s - b) * (s - c))
        return a * b * c / (4 * area)
    }
}